﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ElectronicCommerce.Framework.Configuration;
using ElectronicCommerce.Framework.Configuration.Entities;
using ElectronicCommerce.Framework.ExceptionManagement.Interface;
using ElectronicCommerce.Framework.ExceptionManagement.MessageHandler;

namespace ElectronicCommerce.Framework.ExceptionManagement
{
    // 项目中会用到的表示层名称的枚举，枚举名称对应配置文件中的ExHandler节点的Name属性
    public enum LayerName { DataLayer, BussinessLayer, WebUILayer };
    /// <summary>
    /// ExManager 的摘要说明。
    /// </summary>
    public class ExManager
    {
        /// <summary>
        /// 静态的异常处理配置信息
        /// </summary>
        private static ExManagerConfig exManagerConfig = GetConfig();
        /// <summary>
        /// 静态的异常处理器容器
        /// </summary>
        private static Hashtable htbExHandlers = new Hashtable();

        // 异常处理器对象是否已经加载
        private static bool IsLoadHanlder = false;

        // 实例根据错误代码反查错误信息的类
        private static ExceptionInfo objErrorInfo = new ExceptionInfo(exManagerConfig);

        // 构造函数
        public ExManager()
        {
            if (!IsLoadHanlder)
            {
                GetHandlers();
            }
        }

        /// <summary>
        /// 根据配置文件，反射得到所有的异常处理器实例对象
        /// </summary>
        private void GetHandlers()
        {
            // 遍历配置文件中的所有ExHandler节点
            foreach (Configuration.Entities.ExHandler configHandler in exManagerConfig.ExHandlerList)
            {
                // 根据配置信息，反射得到异常处理类的实例对象，并存到Hashtable中
                ExHandlerBase objHandler = System.Activator.CreateInstance(Type.GetType(configHandler.Type)) as ExHandlerBase;
                objHandler.LoadLogHandler(configHandler);
                htbExHandlers.Add(configHandler.Name, objHandler);
            }
            // 是否加载异常处理实例对象的标志位重置
            IsLoadHanlder = true;
        }

        /// <summary>
        /// Processes the exeception.
        /// </summary>
        /// <param name="ex">The ex.</param>
        /// <param name="strErrorCode">The STR error code.</param>
        /// <param name="strErrorMessage">The STR error message.</param>
        /// <param name="pageAlias">The page alias.</param>
        /// <param name="exHanlderName">Name of the ex hanlder.</param>
        /// <returns></returns>
        public string ProcessExeception(Exception ex, string strErrorCode, string strErrorMessage, string pageAlias, LayerName exHanlderName)
        {
            return ProcessExeception(ex, strErrorCode, strErrorMessage, pageAlias, exHanlderName.ToString(), string.Empty);
        }

        /// <summary>
        /// Processes the exeception.
        /// </summary>
        /// <param name="ex">The ex.</param>
        /// <param name="strErrorCode">The STR error code.</param>
        /// <param name="strErrorMessage">The STR error message.</param>
        /// <param name="pageAlias">The page alias.</param>
        /// <param name="exHanlderName">Name of the ex hanlder.</param>
        /// <returns></returns>
        public string ProcessExeception(Exception ex, string strErrorCode, string strErrorMessage, string pageAlias, string exHanlderName)
        {
            return ProcessExeception(ex, strErrorCode, strErrorMessage, pageAlias, exHanlderName, string.Empty);
        }

        /// <summary>
        /// Processes the exeception.
        /// </summary>
        /// <param name="ex">The ex.</param>
        /// <param name="strErrorCode">The STR error code.</param>
        /// <param name="exHanlderName">Name of the ex hanlder.</param>
        /// <returns></returns>
        public string ProcessExeception(Exception ex, string strErrorCode, LayerName exHanlderName)
        {
            return ProcessExeception(ex, strErrorCode, string.Empty, string.Empty, exHanlderName.ToString(), string.Empty);
        }

        /// <summary>
        /// 调用指定的异常处理器，进行异常处理（提供给系统调用的唯一接口）
        /// </summary>
        /// <param name="ex">The ex.</param>
        /// <param name="strErrorCode">The STR error code.</param>
        /// <param name="strExHanlderName">Name of the STR ex hanlder.</param>
        /// <returns></returns>
        public string ProcessExeception(Exception ex, string strErrorCode, string exHanlderName)
        {
            return ProcessExeception(ex, strErrorCode, string.Empty, string.Empty, exHanlderName, string.Empty);
        }

        /// <summary>
        /// 调用指定的异常处理器，进行异常处理（提供给系统调用的唯一接口）
        /// </summary>
        /// <param name="ex">The ex.</param>
        /// <param name="strErrorCode">The STR error code.</param>
        /// <param name="strExHanlderName">Name of the STR ex hanlder.</param>
        /// <returns></returns>
        public string ProcessExeception(Exception ex, string strErrorCode)
        {
            return ProcessExeception(ex, strErrorCode, string.Empty, string.Empty, "Default", string.Empty);
        }

        /// <summary>
        /// 调用指定的异常处理器，进行异常处理（提供给系统调用的唯一接口）
        /// </summary>
        /// <param name="ex">The ex.</param>
        /// <returns></returns>
        public string ProcessExeception(Exception ex)
        {
            return ProcessExeception(ex, string.Empty, string.Empty, string.Empty, "Default", string.Empty);
        }

        /// <summary>
        /// ProcessExeception方法的重载，提供参数可以选择错误提示窗口的类型（错误/提示信息）
        /// </summary>
        /// <param name="ex">The ex.</param>
        /// <param name="strErrorCode">The STR error code.</param>
        /// <param name="strExHanlderName">Name of the STR ex hanlder.</param>
        /// <param name="strUserId">The STR user id.</param>
        /// <returns></returns>
        private string ProcessExeception(Exception ex, string strErrorCode, string strErrorMessage, string pageAlias, string exHanlderName, string strUserId)
        {
            ExHandlerBase exHandler;
            string strException;

            // 获取指定的异常处理器对象
            try
            {
                exHandler = (ExHandlerBase)htbExHandlers[exHanlderName];
            }
            catch (Exception e)
            {
                // 此处出现异常只能是在开发时
                throw new Exception("指定的异常处理器并不存在，请检查名称是否正确或异常处理器是否正常加载", e);
            }

            MessageBoxType messageType;

            // 执行异常处理过程，若配置信息中返回方式为异常对象，则该函数会在记录异常之后将异常重新包装后抛出
            strException = exHandler.ProcessExeception(ex, strUserId, strErrorCode, string.Empty, string.Empty, out messageType);

            IMessage message = null;

            ExAlertType alertType = (ExAlertType)Enum.Parse(typeof(ExAlertType), exHandler.ExHanlderConfig.AlertType, true);
            // 根据配置信息中指定的异常输出类型不同，确定使用不同的消息对象
            switch (alertType)
            {
                case ExAlertType.WinUi:
                    {
                        //message = new MessageHandler.WinFormMessage();
                        break;
                    }
                case ExAlertType.WebUi:
                    {
                        message = new WebMessage(exHandler);
                        break;
                    }
                case ExAlertType.None:
                    {
                        break;
                    }
                default:
                    {
                        break;
                    }
            }

            // 即ExHanlderConfig.AlertType不等于None
            if (message != null)
            {
                message.ShowMessage(strException, messageType);
            }
            return strException;
        }

        /// <summary>
        /// 根据错误Id获取详细的错误信息
        /// </summary>
        /// <param name="strErrorCode">The STR error code.</param>
        /// <returns></returns>
        public static string GetErrorInfoByCode(string strErrorCode)
        {
            return objErrorInfo.GetErrorInfoById(strErrorCode);
        }

        /// <summary>
        /// 从资源文件ExManagement.ExManagementConfig.Xml中获取
        /// </summary>
        /// <returns></returns>
        private static ExManagerConfig GetConfig()
        {
            return ConfigHelper.ExManagerConfig;
        }
    }
}
